package tt.dz.service.imp.middleware;

import java.lang.reflect.InvocationTargetException;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;

import javax.annotation.Resource;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.jboss.netty.channel.Channel;
import org.jboss.netty.channel.ChannelFuture;
import org.jboss.netty.channel.ChannelFutureListener;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import com.alibaba.fastjson.JSON;

import redis.clients.jedis.Jedis;
import tt.dz.dao.ext.charger.OmsChargerDao;
import tt.dz.entity.base.JsonCommon;
import tt.dz.entity.exception.BizException;
import tt.dz.entity.exception.ChargerNotFoundException;
import tt.dz.entity.exception.FwdServerNotFoundException;
import tt.dz.entity.exception.OmsDaoException;
import tt.dz.entity.system.InstructionLog;
import tt.dz.service.imp.middleware.instruction.Ev3c2Instructions;
import tt.dz.service.imp.middleware.vo.BatteryUploadBody;
import tt.dz.service.imp.middleware.vo.ChargerMsgHeader;
import tt.dz.service.imp.middleware.vo.ChargerReplyMsgHeader;
import tt.dz.service.imp.middleware.vo.ChargerSendingMsgHeader;
import tt.dz.service.imp.middleware.vo.settings.ChargingFeeSettingBody;
import tt.dz.service.imp.middleware.vo.settings.QrCodeSettingBody;
import tt.dz.service.imp.middleware.vo.settings.SerialNoSettingBody;
import tt.dz.service.imp.middleware.vo.settings.ServiceFeeSettingBody;
import tt.dz.service.imp.middleware.vo.settings.SettingBody;
import tt.dz.service.imp.middleware.vo.settings.StateSettingBody;
import tt.dz.service.imp.middleware.vo.settings.TimerSettingBody;
import tt.dz.service.imp.middleware.vo.settings.UserCardSettingBody;
import tt.dz.service.imp.middleware.vo.settings.WhiteListSettingBody;
import tt.dz.service.imp.sys.ChargeDataUploadingVO;
import tt.dz.service.middleware.AnalysisService;
import tt.dz.service.middleware.EncapsulationService;
import tt.dz.service.middleware.LoginService;
import tt.dz.service.middleware.MessageService;
import tt.dz.service.middleware.OmsBespeakService;
import tt.dz.service.middleware.OmsChargeService;
import tt.dz.service.middleware.SetService;
import tt.dz.service.middleware.UploadDataService;
import tt.dz.service.sys.ChargerUploadService;
import tt.dz.service.sys.InstructionLogService;
import tt.dz.tcp.socket.LongConnectionSendMsgImpl;
import tt.dz.tcp.socket.MessageFuture;
import tt.dz.tcp.socket.SendMsg;
import tt.dz.tcp.socket.exception.CreateConnectionFailException;
import tt.dz.tcp.socket.exception.DuplicateInstructionException;
import tt.dz.tcp.socket.exception.RetryFailException;
import tt.dz.tcp.socket.exception.SendMsgTimeOutException;
import tt.dz.util.OmsConstant;
import tt.dz.util.RedisClient;
import tt.dz.util.StringUtil;

@Service
@Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
public class ev3c2MessageServiceImpl implements MessageService {

	private Log log = LogFactory.getLog(ev3c2MessageServiceImpl.class);

	@Resource(name = "longConnectionSendMsgImpl")
	SendMsg sendMsg;
	// DzTcpLongConnectionClient
	// @Resource(name = "dzTcpLongConnectionClient")
	// ISendMsg sendMsg;
	@Resource(name = "ev3c2AnalysisServiceImpl")
	AnalysisService ev3c2AnalysisService;
	@Resource(name = "ev3c2EncapsulationServiceImpl")
	EncapsulationService ev3c2EncapsulationService;
	@Autowired
	LoginService loginService;
	@Autowired
	ChargerUploadService chargerUploadService;
	@Autowired
	UploadDataService uploadDataService;
	@Autowired
	OmsChargeService omsChargeService;
	@Autowired
	OmsBespeakService omsBespeakService;
	@Autowired
	SetService setService;
	@Autowired
	OmsChargerDao omsChargerDao;
	@Autowired
	InstructionLogService insLogDaoService;
	// @Autowired
	// SendShortClientService sendShortClientService;
	// @Resource(name = "ev3c2SendCallBack")
	// ISendCallBack ev3c2SendCallBack;
	@Autowired
	NonNormalResponseHandler nonNormalResponseHandler;

	String ev3c2_magHeader, ev3c2_magBody, frameCode;

	@Override
	public String send(String data) {
		return null;
	}

	// 短连接发送给中间件的格式是 报文
	// 长连接发送给中间件的格式是 data=报文
	@SuppressWarnings({ "rawtypes" })
	@Override
	public JsonCommon receive(Map<String, String> map, Channel channel) throws Exception {
		try {
			log.info(map);

			if (map.get("data") == null)
				throw new BizException("data in response is empty");
			String data = map.get("data");
			String chargerId = (String) map.get("chargerId");
			ChargerMsgHeader responseHeader = this.translateResponseHeader(map);
			if (responseHeader instanceof ChargerReplyMsgHeader) {
				log.info("charger reply");
				ChargerReplyMsgHeader header = (ChargerReplyMsgHeader) responseHeader;
				String replyFor = map.get("replyFor");
				MessageFuture future = null;
				if (replyFor != null) {
					future = LongConnectionSendMsgImpl.getMessageFutureMap().remove(replyFor);
				}

				if (!header.getResponseCode().equals(OmsConstant.MsgResponseCodeEnum.Normal.value())) {
					if (future != null)
						future.setFailure(header.getResponseCode());
					if (nonNormalResponseHandler != null)
						nonNormalResponseHandler.process(header);
					return null;
				} else {
					if (future != null)
						future.setSuccess(data);
					String command = header.getResponseType();
					Ev3c2Instructions instruction = Ev3c2Instructions.parse(command);
					String body = data.substring(74);
					log.info(instruction);
					//无用的数据就不记录了
					insLogDaoService.sendMsg(data, 1, chargerId);
					switch (instruction) {
					// 控制类 异步回复
					case ReserveReply:// 预约 预约电桩（0x11） 电桩回复（0x51） over
						omsBespeakService.ev3c02bespeakReturn(header);
						break;
					case CancelReservationReply:// 预约取消 取消预约电桩（0x12） 电桩回复（0x52）
												// over
						omsBespeakService.ev3c2cancelBespeakReturn(header);
						break;
					case ChargeReply:// 充电 开启充电（0x13） 电桩回复（0x53） over
						startChargeReturn(map, channel);
						break;
					case StopChargingReply:// 关闭充电（0x14） 电桩回复（0x54） over
						stopChargeReturn(map, channel);
						break;
					case ChangeIpReply:// 更改服务器地址IP/PORT（0x15） 电桩回复（0x55） over
						setHardwareServerIpReturn(map, channel);
						break;
					case RestartChargerReply:// 电桩重启回复 重启电桩（0x16） 电桩回复（0x56）
												// over
						restartChargerReturn(map, channel);
						break;
					case SettingsReadWriteReply:// 查询/配置电桩参数（0x21）电桩回复（0xB1）
												// over
						setParamReturn(header, body);
						break;
					default:
						break;
					}
					return null;
				}
			} else if (responseHeader instanceof ChargerSendingMsgHeader) {
				log.info("charger send");
				ChargerSendingMsgHeader header = (ChargerSendingMsgHeader) responseHeader;
				String command = header.getResponseType();
				Ev3c2Instructions instruction = Ev3c2Instructions.parse(command);
				String returnFrameCode = null;
				String body = data.substring(50);
				log.info(instruction);
				// pengyu add
				switch (instruction) {
				case Heart:
				case ChargingStatus:
				case Battery:
					// 可以让联调的人用redis工具远程看
					break;
				default:
					// 按时间排序存入数据库中，不是redis中
//					writeLog(data, (String) chargerId);
					insLogDaoService.sendMsg(data, 2, chargerId);//2为上传
					break;
				}
				switch (instruction) {
				case Register:// 注册签到 注册充电设备地址（0xA1） 服务器回复（0xA2）； over
					returnFrameCode = "A2";
					map.put("returnFrameCode", returnFrameCode);
//					writeLog(data, (String) chargerId);
					chargerRegister(map, channel);
					break;
				case UnRegister:// 2.0中注销 注销充电设备地址（0xA3） 服务器回复（0xA4）； over
					returnFrameCode = "A4";
					map.put("returnFrameCode", returnFrameCode);
					chargerUnRegister(map, channel);
					break;
				case Login:// 设备登陆服务器（0xA5） 服务器回复（0xA6）； over
					returnFrameCode = "A6";
					map.put("returnFrameCode", returnFrameCode);
					// json = null;
					chargerLogin(map, channel);
					break;
				case Logoff:// 设备退出登陆服务器（0xA7） 服务器回复（0xA8）； over
					returnFrameCode = "A8";
					map.put("returnFrameCode", returnFrameCode);
					chargerLogout(map, channel);
					break;
				case Heart:// 心跳（0xA9） 服务器回复（0xAA）； over
					returnFrameCode = "AA";
					map.put("returnFrameCode", returnFrameCode);
					uploadHeart(map, channel);
					break;
				case StatusChange:// 主动遥变上传 状态突变上送（0x22） 服务器回复（0XB2） over
					uploadChange(header, body);
					break;
				case ChargingStatus:// 充电数据上传 充电状态上送（0x23） 服务器回复（0xB3） over
					returnFrameCode = "B3";
					map.put("returnFrameCode", returnFrameCode);
					uploadChargeData(map, channel);
					break;
				case Bill:// 6.5.4 账单主动上传 账单信息上送（0x24） 服务器回复（0XB4）。 over
					returnFrameCode = "B4";
					map.put("returnFrameCode", returnFrameCode);
					uploadBill(map, channel);
					break;
				case Battery:// 6.5.6 电池信息上送（0x25）服务器回复（0XB5）。（直流桩） 电池详情报文（可选）
								// OMS不用回复 over
					uploadBatteryData(header, body);
					break;//
				default:
					break;
				}
			} else
				throw new BizException("Invalid message format, data: " + data);

			return null;
		} catch (Exception e) {
			log.error(e.getMessage(), e);
			throw e;
		} finally {// pengyu add 20161220
			map = null;
		}
	}

	public ChargerMsgHeader translateResponseHeader(Map<String, String> map) throws BizException {
		String data = map.get("data");
		if (data == null)
			throw new BizException("data is null");

		int dataLength = data.length();
		if (dataLength < 50)
			throw new BizException("Header length is invalid, length: " + data.length());

		String chargerId = map.get("chargerId");
		if (chargerId == null || chargerId.length() != 16)
			throw new BizException("charger Id is null or its length is invalid");

		long bodyLength = 2 * StringUtil.int16to10ByParamDesc(data.substring(2, 6));

		ChargerMsgHeader header;
		if (dataLength == 50 + bodyLength)// 桩发起
			header = MessageAnalysisHelper.analyse(data, ChargerSendingMsgHeader.class);
		else if (dataLength == 74 + bodyLength)// 桩回复
			header = MessageAnalysisHelper.analyse(data, ChargerReplyMsgHeader.class);
		else
			throw new BizException("data length is invalid, data: " + data);
		return header;

	}

	@SuppressWarnings("rawtypes")
	private JsonCommon chargerUnRegister(Map<String, String> map, Channel channel) {
		JsonCommon json = new JsonCommon();
		// 解析报文
		map = ev3c2AnalysisService.chargerUnRegister(map);
		// 数据库操作
		map = loginService.ev3c02chargerUnRegister(map);
		// 封装待发送报文
		String msg = ev3c2EncapsulationService.chargerUnRegister(map);
		try {
			channel.write(msg);
			insLogDaoService.sendMsg(msg, 1, (String) map.get("chargerId"));
			Thread.sleep(5000);
			channel.close();
			json.setCode("200");
			json.setMsg("uploadBill return received");
		} catch (Exception e) {
			json.setCode("10303200");
			json.setMsg("chargerLogin return fail sendLongClientService Exception：" + e.getMessage());
			e.printStackTrace();
		}
		return json;
	}

	@SuppressWarnings("rawtypes")
	private void chargerRegister(Map<String, String> map, Channel channel) throws OmsDaoException {
		try {
			// 解析报文
			map = ev3c2AnalysisService.chargerRegister(map);
			// 数据库操作
			map = loginService.ev3c02chargerRegister(map);
			// 封装待发送报文
			final String msg = ev3c2EncapsulationService.chargerRegister(map);
			log.info(msg);
			final String chargerId = (String) map.get("chargerId");
			ChannelFuture future = channel.write(msg);
			
			future.addListener(new ChannelFutureListener() {
				@Override
				public void operationComplete(ChannelFuture future) throws Exception {
					insLogDaoService.sendMsg(msg, 1, chargerId);
					log.info("Message send by channel: " + msg);
				}
			});
		} catch (Exception e) {
			log.error(e.getMessage(), e);
			throw e;
		}
	}

	@SuppressWarnings("rawtypes")
	private JsonCommon updateFirmwareReturn(Map<String, String> map, Channel channel) {
		JsonCommon json = new JsonCommon();
		// 解析报文
		map = ev3c2AnalysisService.updateFirmwareReturn(map);
		// 暂时是没有需要处理的业务，如果以后要处理，则只能存到 oms_charger_software_refresh[桩固件更新记录]中
		return json;
	}

	/**
	 *
	 * @param header
	 * @param body
	 * @throws BizException
	 */
	private void setParamReturn(ChargerReplyMsgHeader header, String body) throws BizException {
		try {
			SettingBody response = MessageAnalysisHelper.analyse(body, SettingBody.class);
			String chargerId = header.getChargerId();

			if ("00".equals(response.getExecuteType()))
				;
			else if ("02".equals(response.getExecuteType()))
				;
			else if ("03".equals(response.getExecuteType()))
				;
			else if ("01".equals(response.getExecuteType())) {
				String settingType = response.getSettingType();
				if (response.isSettingTypeValid(settingType)) {
					Lock lock = QueryService.getChargerLock(chargerId);
					if (lock != null) {
						Condition cond = QueryService.getCondition(chargerId, settingType);
						if (cond != null) {
							lock.lock();
							try {
								if (SettingBody.SettingType_WhiteList.equals(settingType)) {
									WhiteListSettingBody settingBody = MessageAnalysisHelper.analyse(body,
											WhiteListSettingBody.class);
									QueryService.putChargerWhiteList(chargerId, settingBody.getWhiteLists());
									log.info(settingBody.getWhiteLists());
								} else if (SettingBody.SettingType_State.equals(settingType)) {
									StateSettingBody settingBody = MessageAnalysisHelper.analyse(body,
											StateSettingBody.class);
									QueryService.putChargerState(chargerId, settingBody.getState());
									log.info(settingBody.getState());
								} else if (SettingBody.SettingType_ChargingFee.equals(settingType)) {
									ChargingFeeSettingBody settingBody = MessageAnalysisHelper.analyse(body,
											ChargingFeeSettingBody.class);
									QueryService.putChargingFee(chargerId, settingBody.getFeeList(),
											settingBody.getPeriodList());
									log.info(settingBody.getFeeList());
									log.info(settingBody.getPeriodList());
								} else if (SettingBody.SettingType_ServiceFee.equals(settingType)) {
									ServiceFeeSettingBody settingBody = MessageAnalysisHelper.analyse(body,
											ServiceFeeSettingBody.class);
									QueryService.putServiceFee(chargerId, settingBody.getFeeList(),
											settingBody.getPeriodList());
									log.info(settingBody.getFeeList());
									log.info(settingBody.getPeriodList());
								} else if (SettingBody.SettingType_QrCode.equals(settingType)) {
									QrCodeSettingBody settingBody = MessageAnalysisHelper.analyse(body,
											QrCodeSettingBody.class);
									QueryService.putQrCode(chargerId, settingBody.getQrcode());
									log.info(settingBody.getQrcode());
								} else if (SettingBody.SettingType_SerialNo.equals(settingType)) {
									SerialNoSettingBody settingBody = MessageAnalysisHelper.analyse(body,
											SerialNoSettingBody.class);
									QueryService.putSerialNo(chargerId, settingBody.getSerialNo());
									log.info(settingBody.getSerialNo());
								} else if (SettingBody.SettingType_UserCard.equals(settingType)) {
									UserCardSettingBody settingBody = MessageAnalysisHelper.analyse(body,
											UserCardSettingBody.class);
									QueryService.putUserCard(chargerId, settingBody.getCardNo());
									log.info(settingBody.getCardNo());
								} else if (SettingBody.SettingType_Timer.equals(settingType)) {
									TimerSettingBody settingBody = MessageAnalysisHelper.analyse(body,
											TimerSettingBody.class);
									QueryService.putTimer(chargerId, settingBody.getTimer());
									log.info(settingBody.getTimer());
								}
								cond.signalAll();
							} finally {
								lock.unlock();
							}
						}
					}
				}
			} else
				throw new BizException("Invalid execute type");
		} catch (Exception e) {
			log.error(e.getMessage(), e);
			throw e;
		}
	}

	@SuppressWarnings("rawtypes")
	private JsonCommon setWhiteListReturn(Map<String, String> map, Channel channel) {
		JsonCommon json = new JsonCommon();
		try {
			// 解析报文
			map = ev3c2AnalysisService.setWhiteListReturn(map);
			// 处理业务
			json = setService.setWhiteListReturn(map);
		} catch (Exception e) {
			json.setCode("10303200");
			json.setMsg("setWhiteListReturn fail sendLongClientService Exception：" + e.getMessage());
			e.printStackTrace();
		}
		return json;
	}

	@SuppressWarnings("rawtypes")
	private JsonCommon findWhiteListReturn(Map<String, String> map, Channel channel) {
		JsonCommon json = new JsonCommon();
		try {
			// 解析报文
			map = ev3c2AnalysisService.findWhiteListReturn(map);
			// 处理业务 ,存入redis中 setServiceImpl
			json = setService.findWhiteListReturn(map);
		} catch (Exception e) {
			json.setCode("10303200");
			json.setMsg("findWhiteListReturn fail sendLongClientService Exception：" + e.getMessage());
			e.printStackTrace();
		}
		return json;
	}

	@SuppressWarnings("rawtypes")
	private JsonCommon setQrCodeReturn(Map<String, String> map, Channel channel) {
		JsonCommon json = new JsonCommon();
		try {
			// 解析报文
			map = ev3c2AnalysisService.setQrCodeReturn(map);
			// 处理业务
			json = setService.setQrCodeReturn(map);
		} catch (Exception e) {
			json.setCode("10303200");
			json.setMsg("bespeakReturn fail sendLongClientService Exception：" + e.getMessage());
			e.printStackTrace();
		}
		return json;
	}

	@SuppressWarnings("rawtypes")
	private JsonCommon setRateReturn(Map<String, String> map, Channel channel) {
		JsonCommon json = new JsonCommon();
		try {
			// 解析报文
			map = ev3c2AnalysisService.setRateReturn(map);
			// 处理业务 ,处理业务 ,数据存入redis中 setServiceImpl
			json = setService.setRateReturn(map);
		} catch (Exception e) {
			json.setCode("10303200");
			json.setMsg("bespeakReturn fail sendLongClientService Exception：" + e.getMessage());
			e.printStackTrace();
		}
		return json;
	}

	@SuppressWarnings("rawtypes")
	private JsonCommon findRateReturn(Map<String, String> map, Channel channel) {
		JsonCommon json = new JsonCommon();
		try {
			// 解析报文
			map = ev3c2AnalysisService.findRateReturn(map);
			// 处理业务 ,数据存入redis中
			json = setService.findRateReturn(map);
		} catch (Exception e) {
			json.setCode("10303200");
			json.setMsg("bespeakReturn fail sendLongClientService Exception：" + e.getMessage());
			e.printStackTrace();
		}
		return json;
	}

	// 这个方法目前没有必要
	@SuppressWarnings("rawtypes")
	private JsonCommon setTimeReturn(Map<String, String> map, Channel channel) {
		JsonCommon json = new JsonCommon();
		// 解析报文
		map = ev3c2AnalysisService.setTimeReturn(map);
		// 处理业务 ,目前没有地方存这些数据 TODO setServiceImpl
		json = setService.setTimeReturn(map);
		return json;
	}

	@SuppressWarnings("rawtypes")
	private JsonCommon setHardwareServerIpReturn(Map<String, String> map, Channel channel) {
		JsonCommon json = new JsonCommon();
		try {
			// 解析报文
			map = ev3c2AnalysisService.setHardwareServerIpReturn(map);
			// 处理业务
			json = setService.ev3c2setHardwareServerIpReturn(map);
		} catch (Exception e) {
			json.setCode("10303200");
			json.setMsg("setHardwareServerIpReturn fail sendLongClientService Exception：" + e.getMessage());
			e.printStackTrace();
		}
		return json;
	}

	@SuppressWarnings("rawtypes")
	private JsonCommon findHardwareServerIpReturn(Map<String, String> map, Channel channel) {
		JsonCommon json = new JsonCommon();
		try {
			// 解析报文
			map = ev3c2AnalysisService.findHardwareServerIpReturn(map);
			// 处理业务
			json = setService.findHardwareServerIpReturn(map);
		} catch (Exception e) {
			json.setCode("10303200");
			json.setMsg("findHardwareServerIpReturn fail sendLongClientService Exception：" + e.getMessage());
			e.printStackTrace();
		}
		return json;
	}

	@SuppressWarnings("rawtypes")
	private JsonCommon restartChargerReturn(Map<String, String> map, Channel channel) {
		JsonCommon json = new JsonCommon();
		try {
			// 解析报文
			map = ev3c2AnalysisService.restartChargerReturn(map);
			// 处理业务
			json = omsChargeService.ev3c2restartChargerReturn(map);
		} catch (Exception e) {
			json.setCode("10303200");
			json.setMsg("bespeakReturn fail sendLongClientService Exception：" + e.getMessage());
			e.printStackTrace();
		}
		return json;
	}

	@SuppressWarnings("rawtypes")
	private JsonCommon stopChargeReturn(Map<String, String> map, Channel channel) throws Exception {
		JsonCommon json = new JsonCommon();
		try {
			// 解析报文
			map = ev3c2AnalysisService.stopChargeReturn(map);
			// 处理业务,封装待发送报文
			json = omsChargeService.ec3v2stopChargeReturn(map);
			return json;
		} catch (Exception e) {
			log.error("stopChargeReturn fail sendLongClientService Exception：" + e.getMessage(), e);
			throw e;
		}
	}

	@SuppressWarnings("rawtypes")
	private JsonCommon startChargeReturn(Map<String, String> map, Channel channel) {
		JsonCommon json = new JsonCommon();
		try {
			// 解析报文
			map = ev3c2AnalysisService.startChargeReturn(map);
			// 处理业务,封装待发送报文
			json = omsChargeService.ev3c2startChargeReturn(map);
			// String msg = json.getPojo().toString();
			// sendNoWait(msg);
			// sendMsg.send(msg, 0, null);
			// sendShortClientService.send(msg);
			// channel.write(msg);
			// Thread.sleep(5000);
			// channel.close();
			// json.setCode("200");
			// json.setMsg("chargerLogin return received");
		} catch (Exception e) {
			json.setCode("10303200");
			json.setMsg("startCharge return fail sendLongClientService Exception：" + e.getMessage());
			log.error(e.getMessage(), e);
		}
		return json;
	}

	@SuppressWarnings("rawtypes")
	private void chargerLogin(Map<String, String> map, Channel channel)
			throws Exception {
		// 解析报文
		map = ev3c2AnalysisService.chargerLogin(map);
		boolean sendByChannel = false;
		try {
			loginService.ev3c02chargerLogin(map);
			map.put("msgResponseCode", OmsConstant.MsgResponseCodeEnum.Normal.value());
			log.info("login success");
		} catch (ChargerNotFoundException | FwdServerNotFoundException e) {
			log.error(e.getMessage(), e);
			map.put("msgResponseCode", e.getErrorCode());
			sendByChannel = true;
		} catch (BizException e) {
			log.error(e.getMessage(), e);
			map.put("msgResponseCode", e.getErrorCode());
		}

		final String msg = ev3c2EncapsulationService.chargerLogin(map);
		log.info(msg);
		try {
			if (sendByChannel) {
				ChannelFuture future = channel.write(msg);
				insLogDaoService.sendMsg(msg, 1, map.get("chargerId"));
				future.addListener(new ChannelFutureListener() {
					@Override
					public void operationComplete(ChannelFuture future) throws Exception {
						log.info("Message send by channel: " + msg);
					}
				});
			} else{sendMsg.sendAsync(msg, map.get("chargerId"));}
		} catch (CreateConnectionFailException | RetryFailException e) {
			log.error(e.getMessage(), e);
			throw e;
		} catch (DuplicateInstructionException e) {
			log.error("Send message failure, repeat instruction! e = " + e.getMessage(), e);
		}
	}

	@SuppressWarnings("rawtypes")
	private JsonCommon chargerLogout(Map<String, String> map, Channel channel) {
		// JsonCommon json = loginService.dzLoginOut(map);
		JsonCommon json = new JsonCommon();
		// 解析报文
		map = ev3c2AnalysisService.chargerLogout(map);
		// 数据库操作
		map = loginService.ev3c02chargerLogout(map);
		// 封装待发送报文
		String msg = ev3c2EncapsulationService.chargerLogout(map);
		try {
			sendMsg.sendAsync(msg, map.get("chargerId"));
			insLogDaoService.sendMsg(msg, 1, map.get("chargerId"));
			// channel.write(msg);
			// Thread.sleep(5000);
			// channel.close();
			json.setCode("200");
			json.setMsg("uploadBill return received");
		} catch (Exception e) {
			json.setCode("10303200");
			json.setMsg("chargerLogin return fail sendLongClientService Exception：" + e.getMessage());
			e.printStackTrace();
		}
		return json;
	}

	@SuppressWarnings("rawtypes")
	private JsonCommon requestPayByCard(Map<String, String> map, Channel channel) {
		JsonCommon json = new JsonCommon();
		// 解析报文
		// map = ev3c2AnalysisService.requestPayByCard(map.get("data"));
		map = ev3c2AnalysisService.requestPayByCard(map);
		// TODO returnCode 主服务器接口 queryOfflineCard 查询现金卡卡状态
		// queryIdentityCardByNo 查询身份识别卡状态
		String returnCode = "00";
		map.put("returnCode", returnCode);
		// 封装待发送报文
		String msg = ev3c2EncapsulationService.requestPayByCardReturn(map);
		try {
			// sendShortClientService.send(msg);
			// sendMsg.send(msg, 0, null);
			channel.write(msg);
			insLogDaoService.sendMsg(msg, 1, map.get("chargerId"));
			Thread.sleep(5000);
			channel.close();
			json.setCode("200");
			json.setMsg("requestPayByCard return received");
		} catch (Exception e) {
			json.setCode("10303200");
			json.setMsg("requestPayByCard return fail sendLongClientService Exception：" + e.getMessage());
			e.printStackTrace();
		}
		return json;
	}

	// 看看要不要写业务逻辑
	@SuppressWarnings("rawtypes")
	private JsonCommon uploadHeart(Map<String, String> map, Channel channel) {
		JsonCommon json = new JsonCommon();
		// 解析报文
		map = ev3c2AnalysisService.uploadHeart(map);

		map.put("msgResponseCode", OmsConstant.MsgResponseCodeEnum.Normal.value());

		String msg = ev3c2EncapsulationService.uploadHeart(map);
		try {
			String chargerId =map.get("chargerId");
			updateOnLineStatus(chargerId);//更新上线状态
			//发送到中间件
			sendMsg.sendAsync(msg, chargerId);
		} catch (Exception e) {
			log.debug(map);
			log.error(e.getMessage(), e);
		}
		return json;
	}

	private void uploadChange(ChargerSendingMsgHeader header, String data)
			throws CreateConnectionFailException, BizException, RetryFailException {
		try {
			String msg = chargerUploadService.ev3c2uploadChange(header, data);
			sendMsg.sendAsync(msg, header.getChargerId());
		} catch (CreateConnectionFailException | RetryFailException | BizException e) {
			log.error(e.getMessage(), e);
			throw e;
		}
	}

	@SuppressWarnings("rawtypes")
	private JsonCommon uploadFirmwareStatus(Map<String, String> map, Channel channel) {
		JsonCommon json = new JsonCommon();
		// 解析报文
		map = ev3c2AnalysisService.uploadFirmwareStatus(map);
		// 数据库操作
		json = chargerUploadService.uploadFirmwareStatus(map);
		// 封装待发送报文
		String msg = ev3c2EncapsulationService.uploadFirmwareStatusReturn(map);
		try {
			// sendShortClientService.send(msg);
			// sendMsg.send(msg, 0, null);
			channel.write(msg);
			Thread.sleep(5000);
			channel.close();
			json.setCode("200");
			json.setMsg("uploadFirmwareStatus return received");
		} catch (Exception e) {
			json.setCode("10303200");
			json.setMsg("uploadFirmwareStatus return fail sendLongClientService Exception：" + e.getMessage());
			e.printStackTrace();
		}
		return json;
	}

	@SuppressWarnings("rawtypes")
	private JsonCommon uploadBill(Map<String, String> map, Channel channel) throws Exception {

		JsonCommon json = new JsonCommon();
		// 解析报文
		map = ev3c2AnalysisService.uploadBill(map);
		// 数据库操作

		try {
			chargerUploadService.ev3c2uploadBill(map);
			map.put("msgResponseCode", OmsConstant.MsgResponseCodeEnum.Normal.value());
		} catch (Exception ex) {
			log.error(ex.getMessage(), ex);
			map.put("msgResponseCode", OmsConstant.MsgResponseCodeEnum.SysError.value());
		}

		// 封装待发送报文
		String msg = ev3c2EncapsulationService.uploadBill(map);
		try {
			sendMsg.sendAsync(msg, map.get("chargerId"));
		} catch (Exception e) {
			log.error(e.getMessage(), e);
			throw e;
		}
		return json;

	}

	@SuppressWarnings("rawtypes")
	private JsonCommon uploadChargeData(Map<String, String> map, Channel channel) {
		// JsonCommon json = new JsonCommon();
		// //解析报文
		// map = ev3c2AnalysisService.uploadChargeData(map);
		// json.setCode("200");
		// json.setMsg("uploadChargeData return received");
		// return json;
		// JsonCommon json = new JsonCommon();
		// 解析报文
		map = ev3c2AnalysisService.uploadChargeData(map);
		// 数据库操作
		map = chargerUploadService.ev3c2uploadChargeData(map);
		// 封装待发送报文
		String msg = ev3c2EncapsulationService.uploadChargeData(map);
		try {
			String chargerId = map.get("chargerId");
			updateOnLineStatus(chargerId);//更新上线状态
			//发送到中间件
			sendMsg.sendAsync(msg , chargerId);
			// json.setCode("200");
			// json.setMsg("uploadChange return received");
		} catch (Exception e) {
			log.error(e.getMessage(), e);
			// json.setCode("10303200");
			// json.setMsg("uploadChange return fail sendLongClientService
			// Exception：" +e.getMessage());
			// e.printStackTrace();
		}
		return null;

	}

	@SuppressWarnings("rawtypes")
	private void uploadBatteryData(ChargerSendingMsgHeader header, String body) throws InvocationTargetException,
			NoSuchMethodException, InstantiationException, BizException, IllegalAccessException {
		BatteryUploadBody battery = MessageAnalysisHelper.analyse(body, BatteryUploadBody.class);

		// 存入redis中
		String chargerId = header.getChargerId();
		String portNo = header.getPortNo();
		Integer port_No = Integer.valueOf(portNo);
		String key_charging = chargerId + String.format("%02d", port_No) + "_status";

		Jedis jedis = RedisClient.getConnect();
		String json = jedis.get(key_charging);
		ChargeDataUploadingVO vo;
		if (json == null)
			vo = new ChargeDataUploadingVO();
		else
			vo = JSON.parseObject(json, ChargeDataUploadingVO.class);

		vo.setOms_msg_charge_jrnl(battery.getChargingStartingNo());
		vo.setHighestTemperature(
				String.valueOf(StringUtil.convertBinToIntWithNegative(battery.getHighestTemperature(), 1)));

		json = JSON.toJSONString(vo);

		jedis.set(key_charging, json);
		jedis.close();

	}

	@SuppressWarnings({ "rawtypes", "unchecked" })
	private JsonCommon summonReturnUploadTelemetry(Map<String, String> map) {
		JsonCommon json = new JsonCommon();
		// 解析报文
		map = ev3c2AnalysisService.summonReturnUploadTelemetry(map);
		// 数据库操作
		uploadDataService.uploadTelemeter(map);
		// String jsonString = uploadDataService.uploadBill(map);
		// json = JSON.toJSON(jsonString);
		json.setCode("200");
		json.setMsg("uploadBill return received");
		json.setPojo(map);
		return json;
	}

	@SuppressWarnings({ "rawtypes", "unchecked" })
	private JsonCommon summonReturnUploadTelesignal(Map<String, String> map) {
		JsonCommon json = new JsonCommon();
		// 解析报文
		map = ev3c2AnalysisService.summonReturnUploadTelesignal(map);
		// //数据库操作
		uploadDataService.uploadTelesignal(map);
		// String jsonString = uploadDataService.uploadBill(map);
		// json = JSON.toJSON(jsonString);
		json.setCode("200");
		json.setMsg("uploadBill return received");
		json.setPojo(map);
		return json;
	}

	@SuppressWarnings({ "rawtypes", "unchecked" })
	private JsonCommon summonReturnUploadPulse(Map<String, String> map) {
		JsonCommon json = new JsonCommon();
		// 解析报文
		map = ev3c2AnalysisService.summonReturnUploadPulse(map);
		// 数据库操作
		uploadDataService.uploadRemotePulse(map);
		// String jsonString = uploadDataService.uploadBill(map);
		// json = JSON.toJSON(jsonString);
		json.setCode("200");
		json.setMsg("uploadBill return received");
		json.setPojo(map);
		return json;
	}

	@Override
	public String sendAndWait(String msg, long timoutMillisecond) throws RetryFailException, SendMsgTimeOutException {
		// sendMsg.send(msg, 1000*60, ev3c2SendCallBack);
		return null;
		// return sendMsg.sendAndWait(msg, timoutMillisecond);
	}

	@Override
	public MessageFuture sendNoWait(String msg, String chargerid)
			throws RetryFailException, CreateConnectionFailException, DuplicateInstructionException {
		return sendMsg.sendAsync(msg, chargerid);
	}

	@Override
	public JsonCommon receive(String data, Channel c) {

		return null;
	}

	@Override
	public void offlineCharger(String chargerId) {
		log.info("reset charger state");
		// String chargerId = map.get("chargerId");
		// omsChargerDao.exec("update oms_charger_state_alternate set
		// online_status = 0,charge_status = 8 where charger_id ='" + chargerId
		// + "'");
		// omsChargerDao.exec("update oms_charger_state_direct set online_status
		// = 0 ,charge_status = 8 where charger_id ='" + chargerId + "'");
		// pengyu modify 20170105
		omsChargerDao
				.exec("update oms_charger_state_alternate set online_status = 0 where charger_id ='" + chargerId + "'");
		omsChargerDao
				.exec("update oms_charger_state_direct set online_status = 0 where charger_id ='" + chargerId + "'");
		// omsChargerDao.exec("update oms_charger set forward_srv_id = null
		// where charger_id = '"+chargerId +"'");
	}

	@Override
	public void updateOnLineStatus(String chargerId) {
		log.info("updateOnLineStatus chargerId = "+chargerId);
		// String chargerId = map.get("chargerId");
		// omsChargerDao.exec("update oms_charger_state_alternate set
		// online_status = 0,charge_status = 8 where charger_id ='" + chargerId
		// + "'");
		// omsChargerDao.exec("update oms_charger_state_direct set online_status
		// = 0 ,charge_status = 8 where charger_id ='" + chargerId + "'");
		//存入redis中
		if(RedisClient.getMap("heart")==null){
			RedisClient.putMap("heart",new HashMap<String,String>(500));
		}
		HashMap<String,String> chargerHeartMap = (HashMap<String, String>) RedisClient.getMap("heart");
		chargerHeartMap.put(chargerId, String.valueOf(new Date().getTime()));
		RedisClient.putMap("heart", chargerHeartMap);
		// pengyu modify 20170105
		omsChargerDao
				.exec("update oms_charger_state_alternate set online_status = 1 where charger_id ='" + chargerId + "'");
		omsChargerDao
				.exec("update oms_charger_state_direct set online_status = 1 where charger_id ='" + chargerId + "'");
		// omsChargerDao.exec("update oms_charger set forward_srv_id = null
		// where charger_id = '"+chargerId +"'");
	}



//	public void writeLog(String msg, String chargerId){
//		try {
//			log.info("writeLog begin");
//			InstructionLog insLog = new InstructionLog();
//			String frameType = msg.substring(6, 8);
//			log.info("frameType = "+frameType);
//			insLog.setCharger_id(chargerId);
//			insLog.setCreate_time(new Date());
//			insLog.setTransfer_type(Integer.valueOf(2));//上传
//			insLog.setIns_content(msg);
//			insLog.setValid_flag(Integer.valueOf(1));
//			insLog.setFrame_type(frameType);
////			String insName = "注册";
//			String insName = Ev3c2Instructions.parse(frameType).description();
//			log.info(insName);
//			insLog.setIns_name(insName);
//			this.insLogDaoService.add(insLog);
//			log.info("writeLog end");
//		} catch (Exception e) {
//			log.info("writeLog exception:"+e.getMessage());
//		}
//	}
//	public static Ev3c2Instructions getByCode(String code){
//		if(StringUtil.isBlank(code)){
//			return null;
//		}
//		for(Ev3c2Instructions ei :Ev3c2Instructions.values()){
//			if(code.equals(ei.code())){
//				return ei;
//			}
//		}
//		return null;
//	}
//	
//	public static void main(String args[]){
//		System.out.println(getByCode("A1").description());
//	}
}
